/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.nanosn.coffeemaker.asm;

import org.ow2.util.asm.ClassAdapter;
import org.ow2.util.asm.ClassVisitor;
import org.ow2.util.asm.MethodAdapter;
import org.ow2.util.asm.MethodVisitor;
import org.ow2.util.asm.Opcodes;

/**
 * TODO: DO NOT USE !! NOT WORKING!!
 * TODO: USE JARJAR Project to repackage if needed .. http://code.google.com/p/jarjar/
 * @author selkhateeb
 */
public class ClassRenamer extends ClassAdapter implements Opcodes {

    private String newName;
    private String oldName;
    private final String packageName;

    public ClassRenamer(ClassVisitor cv, String packageName) {
        super(cv);
        this.packageName = packageName;
    }

    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        oldName = name;
        newName = packageName + "/" + name;
        System.out.println("============================");
        System.out.println("Class:" + name);
        cv.visit(version, ACC_PUBLIC, newName, signature, superName, interfaces);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        System.out.println("method name = " + name);
        System.out.println("method desc = " + desc);
        System.out.println("method signature = " + signature);
        MethodVisitor mv = cv.visitMethod(access, name, fixDesc(desc), fix(signature), exceptions);
        if (mv != null && (access & ACC_ABSTRACT) == 0) {
            mv = new MethodRenamer(mv);
        }
        return mv;
    }

    class MethodRenamer extends MethodAdapter {

        public MethodRenamer(final MethodVisitor mv) {
            super(mv);
        }

        public void visitTypeInsn(int i, String s) {
            System.out.println("visitTypeInsn s = " + s);
            if (oldName.equals(s)) {
                s = newName;
            }
            mv.visitTypeInsn(i, s);
        }

        public void visitFieldInsn(int opcode, String owner, String name, String desc) {
            System.out.println("owner = " + owner);
            System.out.println("desc = " + desc);
            if (oldName.equals(owner)) {
                mv.visitFieldInsn(opcode, newName, name, fix(desc));
            }
            else {
                mv.visitFieldInsn(opcode, owner, name, fix(desc));
            }
        }

        public void visitMethodInsn(int opcode, String owner, String name, String desc) {
            System.out.println("owner = " + owner);
            System.out.println("desc = " + desc);
            if (oldName.equals(owner)) {
                mv.visitMethodInsn(opcode, newName, name, fix(desc));
            }
            else {
                mv.visitMethodInsn(opcode, owner, name, fix(desc));
            }
        }
    }

    private String fix(String s) {
        if (s != null) {
            s = s.replaceAll(oldName, newName);
        }
//        System.out.println("fix signiture = " + s);
//        if (s != null) {
//            Iterator it = oldNames.iterator();
//            String name;
//            while (it.hasNext()) {
//                name = (String) it.next();
//                if (s.indexOf(name) != -1) {
//                    s = desc.replaceAll(name, newName);
//                }
//            }
//        }
        return s;
    }

    private String fixDesc(String desc) {
        if (desc != null) {
            desc = desc.replace(oldName, newName);
        }
        return desc;
    }
}
